<template>
    <div class="remote-select" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave">
        <input type="text" ref="dhSelectInputRef" class="dh-select-input" :placeholder="props.placeholder"
            v-model="searchQuery" @focus="searchQuery = displayLabel" @input="handleInput" @mousedown="handleMousedown"
            @keydown.down.prevent="moveSelection(1)" @keydown.up.prevent="moveSelection(-1)"
            @keydown.enter.prevent="selectItem(options[activeIndex])" :style="{ width: `${props.width}px` }" />
        <div class="suffix" @click.stop="handleIconClick">
            <el-icon v-if="showClear" key="clear" class="clear-icon" @click="clearSelect" size="14"><CircleClose /></el-icon>
            <el-icon v-else key="arrow" class="caret" :class="{ open: showDropdown }" size="14"><ArrowDown /></el-icon>
        </div>
        <teleport :to="containerTarget" :disabled="!containerTarget">
            <div class="dh-dropdown" ref="dropdownRef" v-if="showDropdown"
                :style="{ minWidth: `${props.width}px`, height: `${props.height}px` }" :id="uid">
                <el-scrollbar>
                    <div class="loader-container" v-if="loading">
                        <div class="spinner-loader">
                            <div class="spinner"></div>                            
                        </div>
                        <div class="loading-text fade-text">
                            <span>加</span><span>载</span><span>中</span><span>.</span><span>.</span><span>.</span>
                        </div>
                    </div>

                    <ul class="dh-dropdown-list" v-else-if="filteredOptions.length && !loading" ref="dropdownListRef"
                        :class="{ 'no-pointer': isScrolling }">

                        <li v-for="(option, index) in filteredOptions" :key="option[props.value]" class="dh-dropdown-item"
                            :class="{ active: index === activeIndex }" @mousedown.prevent="selectItem(option)"
                            @mouseover="handleListMouseOver(index)">
                            <div class="item-text">{{ option[props.label] }}</div>
                        </li>

                    </ul>

                    <div class="dh-dropdown-list" v-else-if="showDropdown && filteredOptions.length === 0 && !loading">
                        <div class="empty">无数据</div>
                    </div>
                </el-scrollbar>
            </div>
        </teleport>
    </div>
</template>

<script setup lang="ts">
import{ArrowDown,CircleClose}from '@element-plus/icons-vue';
import _ from 'lodash';
import { nanoid } from 'nanoid';
const $emit = defineEmits(['change','update:modelValue']);
const modelValue = defineModel<string | number | object | null>({ default: null });
const props = defineProps({
    list: { //回显时用
        type: Array as () => any[],
        default: () => [],
    },
    width: {
        type: Number,
        default: 300,
    },
    height: {
        type: Number,
        default: 300,
    },
    placeholder: {
        type: String,
        default: '请输入关键字'
    },
    value: {
        type: String,
        default: 'value'
    },
    label: {
        type: String,
        default: 'label'
    },
    remoteMethod: Function,
});
const searchQuery = ref('');
const showDropdown = ref(false);
const loading = ref(false);
const activeIndex = ref(-1);
const selectedItem = ref<any>();
const options = ref<any[]>([]);
const dropdownListRef = ref<HTMLElement | null>(null); // 添加对下拉列表的引用
const dhSelectInputRef = ref<HTMLElement | null>(null);
const dropdownRef = ref<HTMLElement | null>(null);
const uid = nanoid(); // 唯一标识当前实例
// 添加滚动状态标志
const isScrolling = ref(false);
// 容器目标选择器
const containerTarget = ref<string | null>(null);
// 创建或获取容器
const ensureContainer = () => {
    const containerId = 'dh-popper-container';
    let container = document.getElementById(containerId);

    if (!container) {
        // 如果容器不存在，则创建它
        container = document.createElement('div');
        container.id = containerId;
        container.style.position = 'absolute';
        container.style.top = '0';
        container.style.left = '0';
        document.body.appendChild(container);
    }

    // 设置Teleport目标
    containerTarget.value = `#${containerId}`;
};


const filteredOptions = computed(() => {
    return options.value;
});
const handleInput = () => {
    if (!showDropdown.value) {
        loading.value = true;
        openDropdwon();
    }
    handleSearch();
}
const handleMousedown = () => {
    if (!showDropdown.value) {
        loading.value = true;
        openDropdwon();
        handleSearch();
    }
}
const openDropdwon = _.debounce(async () => {
    // 等待 DOM 更新    
    const container = document.getElementById('dh-popper-container');
    if (!container) return;
    if (!dhSelectInputRef.value) return;
    const viewportHeight = window.innerHeight;
    const inputRect = dhSelectInputRef.value.getBoundingClientRect();

    showDropdown.value = true;
    document.addEventListener('mousedown', handleClickOutside);
    window.addEventListener('scroll', repositionDropdown);
    window.addEventListener('resize', repositionDropdown);
    await nextTick();
    if (!dropdownRef.value) return;

    const spaceBelow = viewportHeight - inputRect.bottom - 5;
    const spaceAbove = inputRect.top - 5;

    if (spaceBelow >= props.height) {
        // 向下弹出
        dropdownRef.value.style.left = `${inputRect.left}px`;
        dropdownRef.value.style.top = `${inputRect.bottom + window.scrollY + 5}px`;
        dropdownRef.value.style.maxHeight = `${Math.min(spaceBelow, props.height)}px`;
        dropdownRef.value.style.transformOrigin = 'top';
    } else if (spaceAbove >= props.height) {
        // 向上弹出
        dropdownRef.value.style.left = `${inputRect.left}px`;
        dropdownRef.value.style.top = `${inputRect.top + window.scrollY - Math.min(spaceAbove, props.height) - 5}px`;
        dropdownRef.value.style.maxHeight = `${Math.min(spaceAbove, props.height)}px`;
        dropdownRef.value.style.transformOrigin = 'bottom';
    } else {
        // 空间不足，优先向下
        dropdownRef.value.style.left = `${inputRect.left}px`;
        dropdownRef.value.style.top = `${inputRect.bottom + window.scrollY + 5}px`;
        dropdownRef.value.style.maxHeight = `${spaceBelow}px`;
        // dropdownEl.style.overflowY = 'auto';
    }
}, 50);
// 使用防抖优化搜索
const handleSearch = _.debounce(async () => {
    if (!loading.value) {
        loading.value = true;
    }
    try {
        if (!props.remoteMethod) return;
        const results = await props.remoteMethod(searchQuery.value) as unknown as any[];
        options.value = results;
        let index = results.findIndex(item => item.id === modelValue.value);
        activeIndex.value = index;
    } catch (error) {
        console.error('搜索出错:', error);
        options.value = [];
    } finally {
        loading.value = false;
    }

}, 300);


// 处理列表容器上的鼠标悬停事件
const handleListMouseOver = (index: number) => {
    if (isScrolling.value) return;
    // 只更新索引（不会触发滚动）
    activeIndex.value = index;
};

// 添加动画帧控制
let scrollRequestId: number | null = null;
// 键盘导航
const moveSelection = _.throttle((step: number) => {
    if (!showDropdown.value || options.value.length === 0) return;

    let newIndex = activeIndex.value + step;

    if (newIndex < 0) {
        newIndex = options.value.length - 1;
    } else if (newIndex >= options.value.length) {
        newIndex = 0;
    }

    activeIndex.value = newIndex;

    // 添加滚动到选中项的功能
    // 使用 requestAnimationFrame 优化滚动
    if (scrollRequestId) {
        cancelAnimationFrame(scrollRequestId);
    }

    scrollRequestId = requestAnimationFrame(() => {
        scrollToActiveItem();
        scrollRequestId = null;
    });
}, 30, { leading: true, trailing: false });
// 滚动到当前选中项
const scrollToActiveItem = () => {
    if (!dropdownListRef.value || activeIndex.value === -1) return;
    isScrolling.value = true; // 开始滚动

    const items = dropdownListRef.value.querySelectorAll('.dh-dropdown-item');
    if (items.length === 0) return;

    const activeItem = items[activeIndex.value] as HTMLElement;
    if (!activeItem) return;

    // 直接操作滚动容器（比 scrollIntoView 性能更好）
    const scrollContainer = dropdownListRef.value.closest('.el-scrollbar__wrap');
    if (!scrollContainer) return;

    const itemTop = activeItem.offsetTop;
    const itemHeight = activeItem.offsetHeight;
    const containerHeight = scrollContainer.clientHeight;
    const scrollTop = scrollContainer.scrollTop;

    // 计算是否需要滚动
    if (itemTop < scrollTop) {
        // 项目在可视区域上方
        scrollContainer.scrollTop = itemTop;
    } else if (itemTop + itemHeight > scrollTop + containerHeight) {
        // 项目在可视区域下方
        scrollContainer.scrollTop = itemTop + itemHeight - containerHeight;
    }

    // 滚动结束后恢复
    setTimeout(() => {
        isScrolling.value = false;
    }, 100);
};
const displayLabel = ref('');
const syncDisplayLabel = () => {
    if (!modelValue.value) {
        displayLabel.value = '';
        return;
    }
    const hit = [...props.list, ...options.value].find(
        (i) => i[props.value] === modelValue.value
    );
    displayLabel.value = hit ? hit[props.label] : String(modelValue.value);
};
// 选择项目 - 修复了访问未定义对象的问题
const selectItem = (item: any) => {
    let selected = item;

    if (!selected) {
        // 确保索引有效且对象存在
        if (activeIndex.value >= 0 && activeIndex.value < options.value.length) {
            selected = options.value[activeIndex.value];
        }
    }
    if (selected) {
        modelValue.value = selected[props.value];   // v-model 值
        displayLabel.value = selected[props.label]; // 回显文字
        // searchQuery.value = '';                 // 清掉关键词
        showDropdown.value = false;
        document.removeEventListener('mousedown', handleClickOutside);
        window.removeEventListener('scroll', repositionDropdown);
        window.removeEventListener('resize', repositionDropdown);
        $emit('change',selected[props.value],selected[props.label])
        // ✅ 关键：触发 v-model 更新
        $emit('update:modelValue', selected[props.value]);
    }
};

// 点击外部关闭下拉框
const handleClickOutside = (event: any) => {
    if (dhSelectInputRef.value && !dhSelectInputRef.value.contains(event.target) &&
        dropdownRef.value && !dropdownRef.value.contains(event.target)) {
        showDropdown.value = false;
        document.removeEventListener('mousedown', handleClickOutside);
        window.removeEventListener('scroll', repositionDropdown);
        window.removeEventListener('resize', repositionDropdown);
    }
};

const repositionDropdown = () => {
    if (showDropdown.value) {
        openDropdwon();
    }
};
const clearSelect = () => {
    modelValue.value = null;
    displayLabel.value = '';
    searchQuery.value = '';
    selectedItem.value = null;
    activeIndex.value = -1;
    showDropdown.value = false;
    options.value = [];
    $emit('change', null,'');
    $emit('update:modelValue', null);
};
watch(
    () => props.list,
    (newList) => {
        options.value = newList;
        if (!searchQuery.value) syncDisplayLabel();
    },
    { immediate: true }
);
watch(
  () => modelValue.value,
    async (id) => {
        if (!id) {
        displayLabel.value = '';
        searchQuery.value = '';
        return;
        }

        // 1. 本地找
        const hit = [...props.list, ...options.value].find(
        (i) => i[props.value] === id
        );
        if (hit) {
            displayLabel.value = hit[props.label];
            searchQuery.value = hit[props.label];
            let index = filteredOptions.value.findIndex(
            (i) => i[props.value] == id
            );
            activeIndex.value = index;
        } else if (props.remoteMethod) {
            // 2. 远程回显（简单示例：按 id 再查一次）
            const [remoteHit] = await props.remoteMethod(id);
            displayLabel.value = remoteHit ? remoteHit[props.label] : String(id);
            let index = filteredOptions.value.findIndex(
            (i) => i[props.value] == id
            );
            activeIndex.value = index;
        } else {
            displayLabel.value = String(id);
        }
    },
    { immediate: true }
);
const showClear = ref(false);
const onMouseEnter = () => (showClear.value = !!displayLabel.value);
const onMouseLeave = () => (showClear.value = false);

/* 点击图标：箭头展开/收起，✕清空 */
const handleIconClick = () => {
    if (displayLabel.value && showClear.value) return; // 
    toggleDropdown();
};
const toggleDropdown = () => {
    if (showDropdown.value) {
        closeDropdown();
    } else {
        // 点击箭头也触发一次搜索（可选）
        searchQuery.value = displayLabel.value;
        handleInput();
        showDropdown.value = true;
    }
};

const closeDropdown = () => {
    showDropdown.value = false;
};
onMounted(() => {
    // 确保容器存在
    ensureContainer();
});

onUnmounted(() => {
    document.removeEventListener('mousedown', handleClickOutside);
    window.removeEventListener('scroll', repositionDropdown);
    window.removeEventListener('resize', repositionDropdown);
});

</script>

<style scoped lang="scss">
/* 远程搜索下拉框样式 */
.remote-select {
    position: relative;
}

.dh-select-input {
    min-width: 220px;
    height: 28px;
    line-height: 20px;
    padding: 4px 12px;
    border: var(--el-border);
    border-radius: 4px;
    font-size: 13px;
    color: var(--el-text-color-regular);
    background: var(--el-bg-color-overlay);
    transition: all 0.3s;
    outline: none;
    position: relative;
    z-index: 2;

    &::placeholder {
        color: var(--el-text-color-placeholder);
    }
}

.dh-select-input:focus {
    box-shadow: 0 0 0 1px var(--el-color-primary) inset;
}

.dh-dropdown {
    position: absolute;
    min-width: 250px;
    background: var(--el-bg-color-overlay);
    border: var(--el-border);
    border-radius: 6px;
    box-shadow: var(--el-box-shadow);
    z-index: 9999;
    padding: 6px 0 6px 6px;
    transition: all 0.3s;
}

.dh-dropdown-list {
    list-style: none;
    padding-right: 6px;
}

.dh-dropdown-item {
    height: 28px;
    list-style: none;
    padding: 0 15px;
    border-radius: 4px;
    font-size: 13px;
    color: var(--el-text-color-regular);
    cursor: pointer;
    display: flex;
    align-items: center;

    .item-text {
        white-space: nowrap;
    }
}


.dh-dropdown-item.active {
    background: var(--el-color-primary-light-9);
    color: var(--el-color-primary);
}

.empty {
    padding: 10px 15px;
    text-align: center;
    color: var(--el-text-color-secondary);
    font-size: 13px;
}

/* 1. 旋转圆环 + 渐显文字 */
.loader-container {
    gap: 15px;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    padding: 20px;
}

.loading-text {
    font-size: 14px;      
    font-weight: 500;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.spinner-loader {
    position: relative;
    width: 22px;
    height: 22px;
}

.spinner {
    width: 100%;
    height: 100%;
    border: 4px solid var(--el-border-color);
    border-top: 4px solid var(--el-color-primary);
    border-radius: 50%;
    animation: spin 1.2s linear infinite;
}

.fade-text span {    
    color: var(--el-text-color-regular);
    animation: fadeInOut 2s infinite;
}

/* 关键帧动画 */
@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
.dh-select-input {
    position: relative;
    padding-right:35px;
}

.suffix {
    position: absolute;
    right: 8px;
    top: 0;
    bottom: 0;
    width: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 3;
}

/* 图标通用 */
.clear-icon,
.caret {
    font-size: 14px;
    transition: transform 0.3s ease, opacity 0.2s;
    color: var(--el-text-color-placeholder);
}
.caret.open {
    transform: rotate(180deg);
}
</style>
